package com.errol.batchprocessor.employeeaddition.advisorimpl.common;

import com.renjia.enums.EmployeeAuthenticationStatusEnum;
import com.renjia.service.module.employeeaddition.advisorimpl.common.payload.AbstractEmployeeBatchPayload;
import com.renjia.service.module.employeeaddition.advisorimpl.common.payload.AbstractEmployeePiecePayload;
import com.renjia.service.module.employeeaddition.advisorimpl.common.payload.AbstractEmployeeSinglePayload;
import org.springframework.lang.NonNull;

/**
 * 三要素失败时强制通过，用于编辑单条记录的实现继承
 *
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/03/20
 * @since v5.0.6
 **/
public interface ThreeElementForceHandler<BE, SE, BP extends AbstractEmployeeBatchPayload<BE, SE>, PP extends AbstractEmployeePiecePayload<SE, SP>, SP extends AbstractEmployeeSinglePayload<SE>,
        IMPL extends AbstractEmployeeAdvisorImpl<BE, SE, BP, PP, SP>> {

    /**
     * 新增用户时，三要素失败，且满足一定次数，生成待审核用户记录
     *
     * @param singlePayload       单条数据
     * @param piecePayload        分片数据
     * @param batchPayload        批次数据
     * @param employeeAdvisorImpl 用户导入抽象实现的子类
     * @return true 表示处理成功，false 表示失败，拦截
     */
    default boolean forceReviewCoreEmployee(@NonNull SP singlePayload, @NonNull PP piecePayload, @NonNull BP batchPayload, @NonNull IMPL employeeAdvisorImpl) {
        if (batchPayload.isShallForceAuthorized() && Boolean.FALSE.equals(singlePayload.getIsThreeElementSuccess())) {
            // 三要素验证失败，并且要求生成待审核记录(接单导入失败记录，编辑三次都是三要素失败，则强制生成待审核记录，并自动审核通过）
            boolean isInsert = true;
            if (singlePayload.getCoreEmployee() == null) {
                singlePayload.setCoreEmployee(employeeAdvisorImpl.newEmployee(singlePayload, batchPayload));
            } else {
                isInsert = false;
                employeeAdvisorImpl.employeeSupportService.renewalEmployeeOfIdentityInfo(singlePayload.getCoreEmployee(),
                        singlePayload.getEmployeeName(), singlePayload.getDocumentTypeEnum(), singlePayload.getDocumentNumber(), singlePayload.getBankCard());
                singlePayload.setExistEmployeeIdentityAuthed(true);
            }
            singlePayload.getCoreEmployee().setAuthIdentity(EmployeeAuthenticationStatusEnum.AUTHENTICATED.getCode());
            // 线程池外部调用认证接口，此处理先标识为强制认证通过
            singlePayload.getCoreEmployee().setForceAuthenticated(true);
            singlePayload.getCoreEmployee().setCreateAndUpdateUser(batchPayload.getCoreUser());
            if (isInsert) {
                employeeAdvisorImpl.coreEmployeeMapper.insert(singlePayload.getCoreEmployee());
            } else {
                employeeAdvisorImpl.coreEmployeeMapper.updateById(singlePayload.getCoreEmployee());
            }
            singlePayload.setThreeElementSuccess(true);
            singlePayload.getErrMsgList().clear();
            // 处理银行卡的强制认证
            employeeAdvisorImpl.findUserBank(singlePayload, piecePayload, batchPayload);
            return forceReviewUserBank(singlePayload, piecePayload, batchPayload, employeeAdvisorImpl);
        }
        return false;
    }

    /**
     * 检查是否强制验证通过银行卡
     *
     * @param singlePayload       SP
     * @param piecePayload        PP
     * @param batchPayload        BP
     * @param employeeAdvisorImpl 用户导入抽象实现的子类
     * @return true 表示处理成功，false 表示失败，拦截
     */
    default boolean forceReviewUserBank(@NonNull SP singlePayload, @NonNull PP piecePayload, @NonNull BP batchPayload, @NonNull IMPL employeeAdvisorImpl) {
        if (singlePayload.getCoreUserBank() == null) {
            if (batchPayload.isShallForceAuthorized()) {
                singlePayload.setCoreUserBank(employeeAdvisorImpl.newUserBank(singlePayload, batchPayload));
                singlePayload.getCoreUserBank().setForceAuthenticated(true);
                singlePayload.getCoreUserBank().setCreateAndUpdateUser(batchPayload.getCoreUser());
                employeeAdvisorImpl.coreUserBankMapper.insert(singlePayload.getCoreUserBank());

                singlePayload.setThreeElementSuccess(true);
                singlePayload.getErrMsgList().clear();
            }
        }
        return true;
    }
}
